var Random = require('../../utils/random.js');

const CARDS = [
    '2S', '3S', '4S', '5S', '6S', '7S', '8S', '9S', 'TS', 'JS', 'QS', 'KS', 'AS',
    '2H', '3H', '4H', '5H', '6H', '7H', '8H', '9H', 'TH', 'JH', 'QH', 'KH', 'AH',
    '2C', '3C', '4C', '5C', '6C', '7C', '8C', '9C', 'TC', 'JC', 'QC', 'KC', 'AC',
    '2D', '3D', '4D', '5D', '6D', '7D', '8D', '9D', 'TD', 'JD', 'QD', 'KD', 'AD'
];

const HAND_TYPE = {};
HAND_TYPE.WU_XIAO_NIU = 14;
HAND_TYPE.ZHA_DAN = 13;
HAND_TYPE.WU_HUA_NIU = 12;
HAND_TYPE.SI_HUA_NIU = 11;
HAND_TYPE.NIU_NIU = 10;
HAND_TYPE.NIU_JIU = 9;
HAND_TYPE.NIU_BA = 8;
HAND_TYPE.NIU_QI = 7;
HAND_TYPE.NIU_LIU = 6;
HAND_TYPE.NIU_WU = 5;
HAND_TYPE.NIU_SI = 4;
HAND_TYPE.NIU_SAN = 3;
HAND_TYPE.NIU_ER = 2;
HAND_TYPE.NIU_DING = 1;
HAND_TYPE.WU_NIU = 0;

const HAND_TIMES = [
    [1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 8],
    [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 8]
];

const SUITES = {'S': 0.4, 'H': 0.3, 'C': 0.2, 'D': 0.1};

/**
 *
 * @param hands
 * @param config {
 *                "diFen" : 1|2|3,
 *                "bet" [4,2,2,2,...],
 *                "dealerIndex" : -1|0|1|2|3...,
 *                 dealerIndex is -1, 选最大牌型的那位做target
 *                             is not -1, dealerIndex is targetIndex
 *
 *
 *
 *                }
 * @param dealerIndex
 * @param callback
 */
function getResult(hands, config) {
    if (!hands || hands.length === 0) {
        return [];
    }

    var diFen = config["diFen"] || 100;
    var bet = config["bet"] || hands.map(function () {
        return 2;
    });
    var targetIndex = config["dealerIndex"] || -1;
    var multiplierType = config["multiplierType"] || 1;

    var scores = hands.map(function () {
        return 0;
    });

    var ranks = hands.map(function (hand) {
        return calculateNiuResult(hand);
    });

    if (targetIndex === -1) {
        targetIndex = getMaxRankIndex(ranks);
    }

    var targetRank = ranks[targetIndex];
    var handTimes = HAND_TIMES[multiplierType - 1];
    ranks.forEach(function (rank, index) {
        if (targetIndex === index) {
            return;
        }
        var score = diFen * bet[targetIndex] * bet[index];
        if (compareRank(ranks[index], targetRank) > 0) {
            score = score * handTimes[rank.type];
            scores[index] += score;
            scores[targetIndex] -= score;
        } else {
            score = score * handTimes[targetRank.type];
            scores[index] -= score;
            scores[targetIndex] += score;
        }
    });
    return {
        "scores": scores,
        "ranks": ranks
    };
}

function calculateNiuResult(hand) {
    var cardRanks = specialCard(hand);
    if (cardRanks.type !== HAND_TYPE.WU_NIU) {
        return cardRanks;
    }
    return niuCard(hand);
}

function specialCard(hand) {
    var cards = hand.split(' ');
    var ranks = [];
    var powers = [];
    for (let i = 0; i < cards.length; i++) {
        let card = cards[i][0];
        let suit = cards[i][1];
        ranks.push('_A23456789TJQK'.indexOf(card));
        powers.push(ranks[i] + SUITES[suit]);
    }

    var power = Math.max.apply(null, powers);
    ranks.sort(function (src, dst) {
        return dst - src;
    });

    var isWuXiaoNiu = true;
    var isAllTen = true;
    var huaNums = 0;
    var points = 0;
    for (let i = 0; i < ranks.length; ++i) {
        points += ranks[i];
        if (ranks[i] >= 5) {
            isWuXiaoNiu = false;
        }
        if(ranks[i] > 10) {
            huaNums++;
        }
        if (ranks[i] < 10) {
            isAllTen = false;
        }
    }

    if (isWuXiaoNiu && points <= 10) {
        return {type : HAND_TYPE.WU_XIAO_NIU, power : power + (10 -  points) * 15 + HAND_TYPE.WU_XIAO_NIU * 1000, finalCards : hand};
    }

    if (ranks[0] === ranks[1] && ranks[1] === ranks[2] && ranks[2] === ranks[3]) {
        return {type : HAND_TYPE.ZHA_DAN, power : ranks[0] + HAND_TYPE.ZHA_DAN * 1000, finalCards : hand};
    }

    if (ranks[1] === ranks[2] && ranks[2] === ranks[3] && ranks[3] === ranks[4]) {
        return {type : HAND_TYPE.ZHA_DAN, power : ranks[1] + HAND_TYPE.ZHA_DAN * 1000, finalCards : hand};
    }

    if (isAllTen && huaNums === 5) {
        return {type : HAND_TYPE.WU_HUA_NIU, power : power + HAND_TYPE.WU_HUA_NIU * 1000, finalCards : hand};
    }

    if (isAllTen && huaNums === 4) {
        return {type : HAND_TYPE.SI_HUA_NIU, power : power + HAND_TYPE.SI_HUA_NIU * 1000, finalCards : hand};
    }

    return {type : HAND_TYPE.WU_NIU, power : power + HAND_TYPE.SI_HUA_NIU * 1000, finalCards : hand};
}

function niuCard(hand) {
    var cards = hand.split(' ');
    var ranks = [];
    var powers = [];
    for (let i = 0; i < cards.length; i++) {
        let card = cards[i][0];
        let suit = cards[i][1];
        let value =  '_A23456789TJQK'.indexOf(card);
        ranks.push(value > 10 ? 10 : value);
        powers.push(value + SUITES[suit]);
    }
    var power = Math.max.apply(null, powers);
    // var isNiu = ((ranks[0] + ranks[1] + ranks[2]) % 10) === 0 ||
    //             ((ranks[0] + ranks[1] + ranks[3]) % 10) === 0 ||
    //             ((ranks[0] + ranks[1] + ranks[4]) % 10) === 0 ||
    //             ((ranks[0] + ranks[2] + ranks[3]) % 10) === 0 ||
    //             ((ranks[0] + ranks[2] + ranks[4]) % 10) === 0 ||
    //             ((ranks[0] + ranks[3] + ranks[4]) % 10) === 0 ||
    //             ((ranks[1] + ranks[2] + ranks[3]) % 10) === 0 ||
    //             ((ranks[1] + ranks[2] + ranks[4]) % 10) === 0 ||
    //             ((ranks[1] + ranks[3] + ranks[4]) % 10) === 0 ||
    //             ((ranks[2] + ranks[3] + ranks[4]) % 10) === 0;
    var isNiu = false;
    var finalCards = hand;
    if(((ranks[0] + ranks[1] + ranks[2]) % 10) === 0) {
        isNiu = true;
    }else if(((ranks[0] + ranks[1] + ranks[3]) % 10) === 0) {
        finalCards = "" + cards[0] + " " + cards[1] + " " + cards[3] + " " + cards[2] + " " + cards[4];
        isNiu = true;
    }else if(((ranks[0] + ranks[1] + ranks[4]) % 10) === 0) {
        finalCards = "" + cards[0] + " " + cards[1] + " " + cards[4] + " " + cards[2] + " " + cards[3];
        isNiu = true;
    }else if(((ranks[0] + ranks[2] + ranks[3]) % 10) === 0) {
        finalCards = "" + cards[0] + " " + cards[2] + " " + cards[3] + " " + cards[1] + " " + cards[4];
        isNiu = true;
    }else if(((ranks[0] + ranks[2] + ranks[4]) % 10) === 0) {
        finalCards = "" + cards[0] + " " + cards[2] + " " + cards[4] + " " + cards[1] + " " + cards[3];
        isNiu = true;
    }else if(((ranks[0] + ranks[3] + ranks[4]) % 10) === 0) {
        finalCards = "" + cards[0] + " " + cards[3] + " " + cards[4] + " " + cards[1] + " " + cards[2];
        isNiu = true;
    }else if(((ranks[1] + ranks[2] + ranks[3]) % 10) === 0) {
        finalCards = "" + cards[1] + " " + cards[2] + " " + cards[3] + " " + cards[0] + " " + cards[4];
        isNiu = true;
    }else if(((ranks[1] + ranks[2] + ranks[4]) % 10) === 0) {
        finalCards = "" + cards[1] + " " + cards[2] + " " + cards[4] + " " + cards[0] + " " + cards[3];
        isNiu = true;
    }else if(((ranks[1] + ranks[3] + ranks[4]) % 10) === 0) {
        finalCards = "" + cards[1] + " " + cards[3] + " " + cards[4] + " " + cards[0] + " " + cards[2];
        isNiu = true;
    }else if(((ranks[2] + ranks[3] + ranks[4]) % 10) === 0) {
        finalCards = "" + cards[2] + " " + cards[3] + " " + cards[4] + " " + cards[0] + " " + cards[1];
        isNiu = true;
    }
    var niuLevel = (ranks[0] + ranks[1] + ranks[2] + ranks[3] + ranks[4]) % 10;
    if (isNiu) {
        let level = niuLevel !== 0 ? niuLevel : HAND_TYPE.NIU_NIU;
        return {type : level, power : power + level * 1000, finalCards : finalCards};
    } else {
        return {type: HAND_TYPE.WU_NIU, power: power + HAND_TYPE.WU_NIU * 1000, finalCards : finalCards};
    }
}

function getMaxRankIndex(ranks) {
    if (!ranks || ranks.length === 0) {
        return -1;
    }
    var maxIndex = 0;
    for(let i = 1; i < ranks.length; i++) {
        if (compareRank(ranks[i], ranks[maxIndex]) > 0) {
            maxIndex = i;
        }
    }
    return maxIndex;
}

function compareRank(r1, r2) {
    if (r1.type - r2.type > 0) {
        return 1;
    } else if (r1.type - r2.type < 0) {
        return -1;
    }
    return r1.power - r2.power > 0 ? 1 : -1;
}

function cardsToString(cards) {
   var text = '';
   for (var i = 0; i < cards.length; i++) {
       text += cards[i];
       if (i !== cards.length - 1) {
           text += ' ';
       }
   }
   return text;
}

function dealCards(numOfPlayers) {
    var cards = [...CARDS];
    Random.shuffle(cards);
    var hands = [];
    var start = 0;
    for (let i = 0; i < numOfPlayers; i++) {
        let hand = cards.slice(start, start + 5);
        hands.push(cardsToString(hand));
        start = start + 5;
    }
    return hands;
};

exports.getResult = getResult;
exports.dealCards = dealCards;
exports.HAND_TYPE = HAND_TYPE;
exports.calculateNiuResult = calculateNiuResult;

